	package com.unitedvision.persistence.domain;

import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import com.unitedvision.core.domain.CompanyCustomer;
import com.unitedvision.core.domain.Debitur;
import com.unitedvision.core.domain.GeneralType;
import com.unitedvision.core.domain.Status;
import com.unitedvision.core.exception.WrongFormatException;

@Entity
@Table (name = "company_customer")
public class CompanyCustomerEntity implements GeneralType, Debitur {
	private int id;
	private CompanyEntity company;
	private CustomerEntity customer;
	private Status status;
	private long cost;
	private int debt;
	private Date joinDate;
	private List<PaymentEntity> paymentEntities;
	private List<TransactionEntity> transactions;
	
	public CompanyCustomerEntity() {
		super();
	}

	public CompanyCustomerEntity(CompanyCustomer companyCustomer) throws WrongFormatException {
		super();
		this.id = customer.getId();
		this.company = CompanyEntity.create(companyCustomer.getCompany());
		this.customer = CustomerEntity.create(companyCustomer.getCustomer());
		this.status = companyCustomer.getStatus();
		this.cost = companyCustomer.getCost();
		this.debt = companyCustomer.getDebt();
		this.joinDate = companyCustomer.getJoinDate();
	}

	public CompanyCustomerEntity(CompanyEntity companyEntity, CustomerEntity customerEntity, Status status, long cost, int debt, Date joinDate) {
		super();
		this.company = companyEntity;
		this.customer = customerEntity;
		this.status = status;
		this.cost = cost;
		this.debt = debt;
		this.joinDate = joinDate;
	}

	@Id @GeneratedValue
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	@ManyToOne (fetch = FetchType.EAGER)
	@JoinColumn (name = "company_id", referencedColumnName = "id")
	public CompanyEntity getCompany() {
		return company;
	}

	public void setCompany(CompanyEntity companyEntity) {
		this.company = companyEntity;
	}

	@ManyToOne (fetch = FetchType.EAGER)
	@JoinColumn (name = "customer_id", referencedColumnName = "id")
	public CustomerEntity getCustomer() {
		return customer;
	}

	public void setCustomer(CustomerEntity customerEntity) {
		this.customer = customerEntity;
	}

	@Column (name = "status")
	public Status getStatus() {
		return status;
	}

	public void setStatus(Status status) {
		this.status = status;
	}

	@Column (name = "cost")
	public long getCost() {
		return cost;
	}

	public void setCost(long cost) {
		this.cost = cost;
	}

	@Column (name = "debt")
	public int getDebt() {
		return debt;
	}

	public void setDebt(int debt) {
		this.debt = debt;
	}

	@Temporal (TemporalType.DATE)
	@Column (name = "join_date")
	public Date getJoinDate() {
		return joinDate;
	}

	public void setJoinDate(Date joinDate) {
		this.joinDate = joinDate;
	}

	@OneToMany (targetEntity = PaymentEntity.class, mappedBy = "companyCustomer", fetch = FetchType.LAZY)
	public List<PaymentEntity> getPaymentEntities() {
		return paymentEntities;
	}

	public void setPaymentEntities(List<PaymentEntity> paymentEntities) {
		this.paymentEntities = paymentEntities;
	}

	@OneToMany (targetEntity = TransactionEntity.class, mappedBy = "companyCustomer", fetch = FetchType.LAZY)
	public List<TransactionEntity> getTransactions() {
		return transactions;
	}

	public void setTransactions(List<TransactionEntity> transactions) {
		this.transactions = transactions;
	}

	@Transient
	public GeneralType getPayableCustomer() {
		return this;
	}

	@Transient
	public String getCustomerName() {
		return customer.getName();
	}

	@Transient
	public CustomerTypeEntity getCustomerType() {
		return customer.getType();
	}

	@Transient
	public AddressValue getCustomerAddress() {
		return customer.getAddress();
	}

	@Transient
	public ContactValue getCustomerContact() {
		return customer.getContact();
	}

	@Transient
	public String getCompanyName() {
		return company.getName();
	}

	@Transient
	public AddressValue getCompanyAddress() {
		return company.getAddress();
	}

	@Transient
	public ContactValue getCompanyContact() {
		return company.getContact();
	}
	
	@Transient
	public String getCompanyDescription() {
		return company.getDescription();
	}
	
	public CompanyCustomer toCompanyCustomer() {
		return new CompanyCustomer(id, company.toCompany(), customer.toCustomer(), status, cost, debt, joinDate);
	}
	
	public static CompanyCustomerEntity create(CompanyEntity companyEntity, CustomerEntity customerEntity, Status status, long cost, int debt, Date joinDate) {
		return new CompanyCustomerEntity(companyEntity, customerEntity, status, cost, debt, joinDate);
	}
	
	public static CompanyCustomerEntity create(CompanyCustomer companyCustomer) throws WrongFormatException {
		return new CompanyCustomerEntity(companyCustomer);
	}

	@Override
	public String toString() {
		return "CompanyCustomerEntity [id=" + id + ", company=" + company
				+ ", customer=" + customer + ", status=" + status + ", cost="
				+ cost + ", debt=" + debt + ", joinDate=" + joinDate + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((company == null) ? 0 : company.hashCode());
		result = prime * result + (int) (cost ^ (cost >>> 32));
		result = prime * result
				+ ((customer == null) ? 0 : customer.hashCode());
		result = prime * result + debt;
		result = prime * result + id;
		result = prime * result
				+ ((joinDate == null) ? 0 : joinDate.hashCode());
		result = prime * result + ((status == null) ? 0 : status.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		CompanyCustomerEntity other = (CompanyCustomerEntity) obj;
		if (company == null) {
			if (other.company != null)
				return false;
		} else if (!company.equals(other.company))
			return false;
		if (cost != other.cost)
			return false;
		if (customer == null) {
			if (other.customer != null)
				return false;
		} else if (!customer.equals(other.customer))
			return false;
		if (debt != other.debt)
			return false;
		if (id != other.id)
			return false;
		if (joinDate == null) {
			if (other.joinDate != null)
				return false;
		} else if (!joinDate.equals(other.joinDate))
			return false;
		if (status != other.status)
			return false;
		return true;
	}
}
